/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */

import java.util.ArrayList;



interface OMOSetView {

   boolean contains(int element); // testuje na přítomnost prvku v množině
 
   int[] toArray(); //vrátí kopii prvků množiny v poli (na pořadí prvků nezáleží)
 
   OMOSetView copy(); //vrátí kopii množiny
}

// třída reprezentující obecnou množinu, definuje metody add/remove pro přidávání/odebírání prvků
class OMOSet implements OMOSetView {
  ArrayList<Integer> elements;
  
  public OMOSet(){
      this.elements=new ArrayList<>();
  
  }  
  public void add(int element) {
   //přidá prvek "element" do množiny
   if(!elements.contains((Object)element)){elements.add(element);}
  }
 
  public void remove(int element) {
   //odebere prvek "element" z množiny
   elements.remove((Object)element);
   
   }
 
// metody rozhraní OMOSetView

    @Override
    public boolean contains(int element) {
        return elements.contains(element);
    }

    @Override
    public int[] toArray() {
        int[] returnField= new int [elements.toArray().length];
       
        for (int x=0; x<elements.size();x++){
            returnField[x]=elements.get(x);
            
        }
      return returnField;  
    }

    @Override
    public OMOSetView copy() {
        OMOSet returnCopy = new OMOSet();
        for (Integer elem:elements){
            returnCopy.add(elem);
        }
        return returnCopy;
    }
}
 
// třída reprezentující sjednocení dvou množin: A sjednoceno B
class OMOSetUnion implements OMOSetView {
    OMOSetView setA,setB;
   OMOSetUnion(OMOSetView setA, OMOSetView setB) {
    this.setA=setA;
    this.setB=setB;
   }
 
// metody rozhraní OMOSetView

    @Override
    public boolean contains(int element) {
        return (setA.contains(element)||setB.contains(element));
        
    }

    @Override
    public int[] toArray() {
          int i=0;
       
        for (int elem:setA.toArray()){
           if(!setB.contains(elem)){
               
               i++;
           }
            
            
        }
        int[] returnField= new int [i+setB.toArray().length];
         i=0;
        for (int elem:setB.toArray()){
            returnField[i]=elem;
            i++;
        }
        for (int elem:setA.toArray()){
           if(!setB.contains(elem)){
               returnField[i]=elem;
               i++;
           }
            
            
        }
      return returnField;    
    }

    @Override
    public OMOSetView copy() {
        OMOSet returnSet = new OMOSet();
        for (int elem:this.toArray()){
            returnSet.add(elem);
        
        }
        return returnSet;
    }
}
 
// třída reprezentující průnik dvou množin: A průnik B
class OMOSetIntersection implements OMOSetView {
   OMOSetView setA,setB;
   OMOSetIntersection(OMOSetView setA, OMOSetView setB) {
    this.setA=setA;
    this.setB=setB;
   }
 
// metody rozhraní OMOSetView

    @Override
    public boolean contains(int element) {
     return (setA.contains(element)&&setB.contains(element));
    }

    @Override
    public int[] toArray() {
         
        int i=0;
        for (int elem2:setB.toArray()){
           if(setA.contains(elem2)){ 
            i++;}
        }
        int[] returnField= new int [i];
         i=0;
        for (int elem:setB.toArray()){
           if(setA.contains(elem)){ 
             returnField[i]=elem;
            i++;}
        }
        
        return returnField;
    }

    @Override
    public OMOSetView copy() {
         OMOSet returnSet = new OMOSet();
        for (int elem:this.toArray()){
            returnSet.add(elem);
        
        }
        return returnSet;
    }
}
 
// třída reprezentující A\B: doplněk množiny B vzhledem k množině A:  A\B = { x | x∈A ∧ x∉B }
 
class OMOSetComplement implements OMOSetView {
    OMOSetView setA,setB;
   OMOSetComplement(OMOSetView setA, OMOSetView setB) {
       this.setA=setA;
       this.setB=setB;
   }
 
// metody rozhraní OMOSetView

    @Override
    public boolean contains(int element) {
        return (setA.contains(element)&& !setB.contains(element));
    }

    @Override
    public int[] toArray() {
       
        int i=0;
        for (int elem2:setA.toArray()){
           if(!setB.contains(elem2)){
            i++;}
        }
        
         int[] returnField= new int [i];
         i=0;
         for (int elem:setA.toArray()){
           if(!setB.contains(elem)){ returnField[i]=elem;
            i++;}
        }
        return returnField;
    }

    @Override
    public OMOSetView copy() {
         OMOSet returnSet = new OMOSet();
        for (int elem:this.toArray()){
            returnSet.add(elem);
        
        }
        return returnSet;
    }
}
 
// třída reprezentující množinu sudých čísel 
class OMOSetEven implements OMOSetView {
    OMOSetView setA;
    OMOSetEven(OMOSetView setA) {
        this.setA=setA;
 
    }
// metody rozhraní OMOSetView

    @Override
    public boolean contains(int element) {
        return setA.contains(element)&&(element%2==0);
    }

    @Override
    public int[] toArray() {
         int i=0;
        for (int elem2:setA.toArray()){
           if(elem2%2==0){ 
            i++;}
        }
        int[] returnField= new int [i];
         i=0;
        for (int elem:setA.toArray()){
           if(elem%2==0){ returnField[i]=elem;
            i++;}
        }
        return returnField;
    }

    @Override
    public OMOSetView copy() {
        OMOSet returnSet = new OMOSet();
        for (int elem:this.toArray()){
            returnSet.add(elem);
        
        }
        return returnSet;
    }
}


